package com.cjzuji.rental.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.cjzuji.rental.Bean.YoupinRequest;
import com.cjzuji.rental.Config.ProjectConfig;
import com.cjzuji.rental.Config.YpConfig;
import com.cjzuji.rental.controller.order.YouPinController;
import com.cjzuji.rental.dao.*;
import com.cjzuji.rental.mapper.OrderBillMapper;
import com.cjzuji.rental.mapper.OrderMapper;
import com.cjzuji.rental.mapper.OrderUserMapper;
import com.cjzuji.rental.pojo.*;
import com.cjzuji.rental.service.YouPinService;
import com.cjzuji.rental.util.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.annotations.Update;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.*;

@Service
public class YouPinServiceImpl implements YouPinService {
    @Autowired
    OrderDao orderDao;
    @Autowired
    OrderMapper orderMapper;
    @Autowired
    OrderBillMapper orderBillMapper;
    @Autowired
    OrderUserDao orderUserDao;
    @Autowired
    OrderContractDao orderContractDao;
    @Autowired
    OrderBillDao orderBillDao;
    @Autowired
    YpConfig ypConfig;
    @Autowired
    OrderUserMapper orderUserMapper;
    @Autowired
    ProjectConfig projectConfig;
    @Autowired
    RiskApprovilDao riskApprovilDao;
    private static final Logger logger = LoggerFactory.getLogger(YouPinController.class);
    @Override
    //http://127.0.0.1:9099/order/youping/getListInfo
    public List<Map<String, Object>> getOrderssList(String accesstoken, String authorization) {
        String url = ypConfig.getGetListUrl();
        YoupinRequest youpinRequest = new YoupinRequest();
        List<Map<String, Object>> listData = new ArrayList<>();
        youpinRequest.setModel("transferAllList");
        youpinRequest.setPageNo(0);
        youpinRequest.setPageSize(20);
        youpinRequest.setTransferMerchantTag(2);
        int pageNum = 0;  // 从第一页开始
        // 2. 转换为 JSON
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectMapper resMapper = new ObjectMapper();
        ObjectMapper resDetailMapper = new ObjectMapper();
        ObjectMapper resUserMapper = new ObjectMapper();
        while (true) {
            try {
                youpinRequest.setPageNo(pageNum);
                String json = objectMapper.writeValueAsString(youpinRequest);
                String resStr = Tool.request(url,accesstoken,authorization,json,"", "");
                //logger.info(resStr);
                Map<String,Object> res = resMapper.readValue(resStr,Map.class);
                // 获取 data → list
                Map<String, Object> dataMap = (Map<String, Object>) res.get("data");
                //logger.info("dataMap~~ {}",dataMap);
                List<Map<String, Object>> list = (List<Map<String, Object>>) dataMap.get("list");
                //logger.info("list~~~ {}",list);
                if (list != null && list.size() > 0) {
                    for (Map<String, Object> item : list) {
                        //查询订单详情
                        String detail = ypConfig.getGetDetailUrl() + "?loanId=" + item.get("id");
                        String detailStr =  Tool.getRequest(detail,authorization,accesstoken, "");
                        Map<String,Object> resDel = resDetailMapper.readValue(detailStr,Map.class);
                        Map<String,Object> detailMap = (Map<String, Object>) resDel.get("data");
                        List<Map<String,Object>>  contractDtoList = (List<Map<String, Object>>) detailMap.get("contractDtoList");
//                    logger.info("打印dataDetail {}",resDel);
                        //获取用户信息
                        String userUrl = ypConfig.getGetUserUrl();
                        List<String> userParam = new ArrayList<>();
                        userParam.add(item.get("receiverName").toString());  // 收货人名称
                        userParam.add(item.get("receiverMobile").toString());  //收货人手机
                        userParam.add(item.get("receiverAddressFormat").toString());  // 收货地址
                        userParam.add(item.get("mobile").toString());  //
                        userParam.add(item.get("idcardNo").toString());  //
                        userParam.add(null);  //
                        //logger.info("打印用户信息请求参数 {}",userParam);
                        //将参数转json
                        String userParamStr = objectMapper.writeValueAsString(userParam);
                        //logger.info("打印用户信息请求参数str {}",userParamStr);
                        String userRes =  Tool.request(userUrl,authorization,authorization,userParamStr,item.get("no").toString(), "");
                        Map<String,Object> resUser =  resUserMapper.readValue(userRes,Map.class);
                        List<String> userInfo = (List<String>) resUser.get("data");
                        String orderNo = item.get("no").toString();
                        // 判断 当前的订单号是否在数据库中存在 如果存在  跳出当前循环
                        QueryWrapper<Orders> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("order_id",item.get("no").toString());
                        List<Orders> existingOrder = orderMapper.selectList(queryWrapper);
                        //System.out.println(item.get("surplusBondAmt"));
                        logger.info("existingOrder {}",existingOrder);
                        if (existingOrder.size() > 0 ) {
                            // 订单已存在，跳过当前循环
                            logger.info("订单已存在，跳过当前循环");
                            if (existingOrder.get(0).getStatus() == 9){
                                logger.info("状态为9，跳过");
                            }else {
                                int newStatus = getOrderStatus(item.get("status").toString(),item);
                                String deliveryNo = "";
                                if (newStatus == 3 || newStatus == 4 || newStatus == 5){
                                    deliveryNo = item.get("orderNo").toString();
                                }
                                UpdateWrapper<Orders> updateWrapper = new UpdateWrapper<>();
                                updateWrapper.eq("order_id",orderNo)
                                        .set("status",newStatus)
                                        .set("delivery_no",deliveryNo);
                                logger.info("更新订单状态 {} ",newStatus);
                                orderMapper.update(updateWrapper);
                            }

                        }
                        else{
                            Long orderID = orderDao.save(item,detailMap,userInfo);
                            orderUserDao.save(detailMap,orderID,userInfo);
//                            //调用风控审批接口
//                            String riskApp = riskApproval(existingOrder.get(0),orderNo);
//                            logger.info("风控审批接口完成，返回creditId {}",riskApp);
//                            //调用风控查询接口
//                            queryApproval(riskApp);
                            orderContractDao.save(contractDtoList,orderID);
                            //当订单状态为orderStatus!=55时，有账单信息表
                            logger.info("打印detailMap {}",detailMap);
                            if ("15".equals(item.get("status").toString()) || "220".equals(item.get("status").toString()) || "210".equals(item.get("status").toString())) {
                                List<Map<String,Object>>  billDtoList = (List<Map<String, Object>>) detailMap.get("planList");
                                //logger.info("打印billDtoList  {}",billDtoList);
                                if (billDtoList.size() > 0) {
                                    orderBillDao.save(billDtoList, orderID, orderNo);
                                }
                            }
                        }
                    }
                }else {
                    break;
                }
                pageNum ++;
                logger.info("打印当前页码 {}",pageNum);

            } catch (JsonProcessingException e) {
                logger.info(e.getMessage());
                break;
            }
        }
        return listData;
    }

    //租用中
    @Override
    public List<Map<String, Object>> upDateBillList(String accesstoken, String authorization, String model) {
        String url = ypConfig.getGetListUrl();
        YoupinRequest youpinRequest = new YoupinRequest();
        List<Map<String, Object>> listData = new ArrayList<>();
        youpinRequest.setModel(model);
        youpinRequest.setPageNo(0);
        youpinRequest.setPageSize(20);
        youpinRequest.setTransferMerchantTag(2);
        int pageNum = 0;  // 从第一页开始
        // 2. 转换为 JSON
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectMapper resMapper = new ObjectMapper();
        ObjectMapper resDetailMapper = new ObjectMapper();
        ObjectMapper resUserMapper = new ObjectMapper();
        while (true) {
            try {
                youpinRequest.setPageNo(pageNum);
                String json = objectMapper.writeValueAsString(youpinRequest);
                String resStr = Tool.request(url,accesstoken,authorization,json,"", "");
                //logger.info("获取请求结果~~",resStr);
                Map<String,Object> res = resMapper.readValue(resStr,Map.class);
                Map<String, Object> dataMap = (Map<String, Object>) res.get("data");
                List<Map<String, Object>> list = (List<Map<String, Object>>) dataMap.get("list");
                if (list != null && list.size() > 0) {
                    for (Map<String, Object> item : list) {
                        //查询订单详情
                        String detail = ypConfig.getGetDetailUrl() + "?loanId=" + item.get("id");
                        String detailStr =  Tool.getRequest(detail,authorization,accesstoken, "");
                        Map<String,Object> resDel = resDetailMapper.readValue(detailStr,Map.class);
                        Map<String,Object> detailMap = (Map<String, Object>) resDel.get("data");
                        List<Map<String,Object>>  contractDtoList = (List<Map<String, Object>>) detailMap.get("contractDtoList");
                        List<Map<String,Object>>  billDtoList = (List<Map<String, Object>>) detailMap.get("planList");
                        //logger.info("打印dataDetail {}",resDel);
                        String orderId = item.get("no").toString();
                        //logger.info("打印orderId {}",orderId);
                        // 判断 当前的订单号是否在数据库中存在 如果存在  跳出当前循环
                        QueryWrapper<OrderBill> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("orders_id",orderId);
                        List<OrderBill> existingBill = orderBillMapper.selectList(queryWrapper);
                        logger.info("查询到的已存在账单数量: {}",existingBill.size());
                        // 订单已存在
                        if (!existingBill.isEmpty() ) {
                            Long orderID = existingBill.get(0).getOrderId();
                            // 订单已存在，对比两方的“还款状态”数据，如果相同不变，不同对数据库账单表进行更新
                            logger.info("订单已存在~~,对比更新数据",orderId);
                            compareUpdate(item,billDtoList,existingBill,orderID);

                        }
                        //不存在，添加进数据库，合同表和账单表 , 更新orders表
                        else{
                            QueryWrapper<Orders> orderWrapper = new QueryWrapper<>();
                            orderWrapper.eq("order_id",orderId);
                            Orders order = orderMapper.selectOne(orderWrapper);
                            if(order != null){
                                //更新orders表中的很多列数据，如：分配人，押金，订单状态，碎屏险，碎屏险状态，快递单号，订单更新时间
                                Map<String,Object> orderRemarkLog = (Map<String, Object>) item.get("orderRemarkLog");
                                String operationName = "";
                                if (orderRemarkLog != null){
                                    operationName = orderRemarkLog.get("operationName").toString();
                                    //logger.info("打印操作人 {}",operationName);
                                }
                                double screenRisksAmount = 0;
                                int risksType = 0;
                                //ogger.info("打印 {}",dataMap);
                                //logger.info("打印碎屏险金额 {}", detailMap.get("realPayScreenRisksAmount").toString());
                                if (!detailMap.get("realPayScreenRisksAmount").toString().equals("0")){
                                    //logger.info("打印碎屏险金额存在");
                                    screenRisksAmount = Double.parseDouble(detailMap.get("realPayScreenRisksAmount").toString()) ;
                                    //logger.info("打印碎屏险金额 {}",screenRisksAmount);
                                    risksType = 1;
                                    //logger.info("打印碎屏险状态 {}",risksType);
                                }
                                UpdateWrapper<Orders> updateWrapper = new UpdateWrapper<>();
                                updateWrapper.eq("order_id",orderId)
                                        .set("assigner",operationName)   //分配人
                                        .set("surplus_bond_amt",Double.parseDouble(item.get("surplusBondAmt").toString()))  //押金
                                        .set("status",3)     //订单状态
                                        .set("screen_risks_amount",screenRisksAmount)  //碎屏险
                                        .set("screen_risks_type",risksType)   //碎屏险状态
                                        .set("delivery_no",item.get("orderNo"))   //快递单号
                                        .set("update_time",new Date());   //订单更新时间
                                logger.info("打印更新数据 {}",updateWrapper);
                                orderMapper.update(null,updateWrapper);
                                Long orderID = order.getId();
                                logger.info("打印orderID {}",orderID);
                                logger.info("添加合同表~~",orderId);
                                orderContractDao.save(contractDtoList,orderID);
                                logger.info("添加账单表~~",orderId);
                                orderBillDao.save(billDtoList,orderID, orderId);
                            }else {
                                logger.info("Orders表中未找到订单~~~",orderId);
                            }
                        }
                    }
                }else {
                    break;
                }
                pageNum ++;
                logger.info("打印当前页码 {}",pageNum);
            } catch (JsonProcessingException e) {
                logger.info(e.getMessage());
                break;
            }
        }
        return listData;
    }

    //对比更新代码
    public void compareUpdate(Map<String, Object> item,List<Map<String, Object>> billDtoList,List<OrderBill> existingBill, Long orderID) {
        //存在orders中，但是可以过了一段时间，订单状态可能会变成逾期，所以还要更新ordersa表中的订单状态
        if (Integer.parseInt(item.get("overdueDays").toString()) > 0){
            UpdateWrapper<Orders> orderupdateWrapper = new UpdateWrapper<>();
            orderupdateWrapper.eq("id",orderID)
                    .set("status",4);
        }
        //System.out.println("billDtoList~~:"+billDtoList);
        //创建一个Map，用于存储数据库中的账单
        Map<Integer, OrderBill> existingBillMap = new HashMap<>();
        for (OrderBill bill : existingBill) {
            existingBillMap.put(bill.getTerm(), bill);
        }
        //logger.info("existingBillMap {}",existingBillMap);
        for (Map<String, Object> billDto : billDtoList) {
            Integer term = (Integer) billDto.get("term");
            String newStatus = billDto.get("repayStatusStr") != null ? billDto.get("repayStatusStr").toString() : "";
            OrderBill oldBill = existingBillMap.get(term);
            if (oldBill != null) {
                //对比订单状态
                String oldStatus = oldBill.getRepayStatusStr() != null ? oldBill.getRepayStatusStr() : "";
                //System.out.println("oldStatus~~ " + oldStatus);
                if(!newStatus.equals(oldStatus)){
                    //状态不同
                    logger.info("状态不同，第{}期~~", term);
                    UpdateWrapper<OrderBill> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.eq("id", oldBill.getId())
                            .set("real_pay_time", billDto.get("realRepayTime")) //支付时间
                            .set("real_pay_capital", billDto.get("realRepayCapital"))  //实付金额
                            .set("overdue_amount", billDto.get("realOverdueFine"))  //逾期金额
                            .set("repay_status_str", newStatus) // 还款状态
                            .set("real_pay_trade_id", billDto.get("thirdPartOrderNo"))  //商家交易号
                            .set("real_repay_time", billDto.get("realRepayTime"))//还款时间
                            .set("update_time", new Date());
                    //updateBill.setId(oldBill.getId()); //设置要更新的Id
                    //更新数据库
                    //orderBillMapper.updateById(updateBill);
                    orderBillMapper.update(null,updateWrapper);
                }else {
                    //logger.info("状态相同，第{}期~~", term);
                }
            }
        }
    }
    //订单状态枚举
    public int getOrderStatus(String status,Map<String, Object> item) {
        switch (status) {
            case "1":   //待发货
                return 1;
            case "5":  //已发货
                return 2;
            case "15":  //租用中
                if (Integer.parseInt(item.get("overdueDays").toString()) > 0){
                    return 4;  //逾期
                }else {
                    return 3;
                }
            case "55":   //待审核
                return 0 ;
            case "220":   //已完成
                return 5;
            case "210":   //已归还
                return 5;
            default:
                return 7;
        }
    }
    //风控授信
    @Override
    public String riskApproval(Orders orders,String orderId) {
        //获取风控优品信息
        QueryWrapper<OrderUser> queryWrapper = new QueryWrapper();
        queryWrapper.eq("order_id", orders.getId());
        //这里注入OrderUserMapper，根据orderId查询
        OrderUser orderUser = orderUserMapper.selectOne(queryWrapper);
        JSONObject content = new JSONObject();
        content.put("idcard_no", orderUser.getIdCard());    // 身份证号
        content.put("mobile", orders.getPhone());      // 手机号
        content.put("name", orders.getRealName());    // 姓名
        content.put("receive_address", orderUser.getAddressInfo());   //收货地址
        content.put("orderNo", orderId);  // 订单号
        //content.put("leaseScheme", "1");   //租赁类型
        content.put("channelNo", orders.getShopId());   //租赁渠道
        //content.put("userid", orders.getLeaseTerm());   //用户ID
        content.put("credit_time", DateUtil.getStandardNowTime());   //授信时间
        String creditId =  java.util.UUID.randomUUID().toString().replace("-", "");
        content.put("credit_id", creditId);  //授信ID
        content.put("releaseChannel", orders.getPlatformId());  //投流渠道
        String contentStr = JSONObject.toJSONString(content);
        logger.info("风控审批入参信息：{}",contentStr);
        //AES加密
        String encryptedContent = AESUtilsOfThird.encryptAES(contentStr, projectConfig.getAESKEY());
        logger.info("AES加密后的内容：{}",encryptedContent);
        //MD5
        String md5Content = MD5.getMd5(encryptedContent);
        logger.info("MD5加密后的内容：{}",md5Content);
        //RSA sign
        String signString = "";
        try {
            signString = RSAUtil.sign(md5Content, projectConfig.getPRIVATEKEY(), false);
            logger.info("得到的签名是：" + signString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        JSONObject params = new JSONObject();
        params.put("source_id", projectConfig.getSOURCEID());
        params.put("event_code", projectConfig.getAPPROVALEVENTCODE());
        params.put("signature", signString);
        params.put("content", encryptedContent);
        logger.info("风控接口请求入参:{}",JSONObject.toJSONString(params));
        String result = HttpClientUtil.postJson(projectConfig.getURL(), params);
        logger.info("风控接口响应:"+result);
        JSONObject resultObj = JSONObject.parseObject(result);
        //判断接口是否调用成功
        if (resultObj.getString("status").equals("1000")){
            String needDecryptString = resultObj.getString("content");
            String resultContentStr = AESUtilsOfThird.decryptAES(needDecryptString, projectConfig.getAESKEY());
            logger.info("返回Content: " + resultContentStr);
            JSONObject contentObject = JSONObject.parseObject(resultContentStr);
            RiskApprovil approval = riskApprovilDao.getOne(new QueryWrapper<RiskApprovil>().eq("order_id",orderId).last("limit 1"));
            if (approval== null){
                approval = new RiskApprovil();
            }
            approval.setOrderId(orders.getId());
            approval.setOrdersId(orderId);
            approval.setContent(resultContentStr);
            approval.setApprovalStatus(ObjectUtils.isNotEmpty(contentObject) ?contentObject.getString("approval_status"):null);
            approval.setCreditId(creditId);
            approval.setCreateTime(new Date());
            approval.setUpdateTime(new Date());
            riskApprovilDao.saveOrUpdate(approval);
            return creditId;
        }else {
            return null;
        }
    }
    /**
     *  查询风控授信处理结果
     * @param creditId  查询引擎授信处理结果
     * @return
     */
    public String queryApproval(String creditId) {
        JSONObject content = new JSONObject();
        content.put("credit_id", creditId);
        String contentStr = JSONObject.toJSONString(content);
        logger.info("查询风控接口处理结果入参:"+contentStr);
        // AES
        String encryptedContent = AESUtilsOfThird.encryptAES(contentStr, projectConfig.getAESKEY());
        logger.info("AES加密后的内容："+encryptedContent);
        // MD5
        String md5Content = MD5.getMd5(encryptedContent);
        logger.info("md5加密后的内容："+md5Content);
        // RSA sign
        String signString = "";
        try {
            signString = RSAUtil.sign(md5Content, projectConfig.getPRIVATEKEY(), false);
            logger.info("得到的签名是：" + signString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        JSONObject params = new JSONObject();
        params.put("source_id", projectConfig.getSOURCEID());
        params.put("event_code", projectConfig.getAPPROVALRESULTEVENTCODE());
        params.put("signature", signString);
        params.put("content", encryptedContent);
        logger.info("查询风控接口处理结果请求入参:{}",JSONObject.toJSONString(params));
        String result = HttpClientUtil.postJson(projectConfig.getQUERYURL(), params);
        logger.info("查询风控接口处理结果响应:"+result);
        JSONObject resultObj = JSONObject.parseObject(result);
        //判断接口调用是否成功
        if (resultObj.getString("status").equals("1000")){
            String needDecryptString = resultObj.getString("content");
            String resultContentStr = AESUtilsOfThird.decryptAES(needDecryptString, projectConfig.getAESKEY());
            logger.info("返回Content: " + resultContentStr);
            JSONObject contentObject = JSONObject.parseObject(resultContentStr);
            RiskApprovil approval = riskApprovilDao.getOne(new QueryWrapper<RiskApprovil>().eq("credit_id",creditId).last("limit 1"));
            if (approval== null){
                approval = new RiskApprovil();
            }
            approval.setMassage(resultContentStr);
            approval.setStatus(ObjectUtils.isNotEmpty(contentObject) ?contentObject.getString("status"):null);
            approval.setApprovalStatus(ObjectUtils.isNotEmpty(contentObject) ?contentObject.getString("approval_status"):null);
            approval.setCreditId(creditId);
            approval.setUpdateTime(new Date());
            riskApprovilDao.saveOrUpdate(approval);
            return resultContentStr;
        }else {
            return null;
        }

    }
}